home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1999 March / EnigmA AMIGA RUN 35 (1999)(G.R. Edizioni)(IT)[!][issue 1999-03].iso / earcd / devel / vbcc-ppc-src / pasm / eval.c < prev    next >
C/C++ Source or Header  |  1999-01-01  |  22KB  |  828 lines

  1. /* $VER: pasm eval.c V1.2 (21.10.98)
  2.  *
  3.  * This file is part of pasm, a portable PowerPC assembler.
  4.  * Copyright (c) 1997-98  Frank Wille
  5.  *
  6.  * pasm is freeware and part of the portable and retargetable ANSI C
  7.  * compiler vbcc, copyright (c) 1995-98 by Volker Barthelmann.
  8.  * pasm may be freely redistributed as long as no modifications are
  9.  * made and nothing is charged for it. Non-commercial usage is allowed
  10.  * without any restrictions.
  11.  * EVERY PRODUCT OR PROGRAM DERIVED DIRECTLY FROM MY SOURCE MAY NOT BE
  12.  * SOLD COMMERCIALLY WITHOUT PERMISSION FROM THE AUTHOR.
  13.  *
  14.  *
  15.  * v1.2   (21.10.98) phx
  16.  *        @sdarx and @sdax are recognized and generate a R_PPC_SDAREL16
  17.  *        relocation.
  18.  *        Replaced obsolete R_PPC_TOC16 by real R_PPC_SDAREL16.
  19.  * v1.1e  (19.10.98) phx
  20.  *        Improved hihalf(): >> instead /
  21.  * v1.0   (04.04.98) phx
  22.  *        ADDR16-relocation/xref works for instructions, like addi, cmpi, etc.
  23.  * v0.9   (07.03.98) phx
  24.  *        The EHF-offset for R_REL14 is handled in instructions.c. No need
  25.  *        to increase the return value in makexref() and makereloc().
  26.  * v0.7   (01.01.98) phx
  27.  *        @ha, @h, @l are only allowed at the end of an operand, according
  28.  *        to GNU-as notation. '@' is only allowed as the first character in
  29.  *        a symbol (for @function and @object, for example).
  30.  *        Don't waste memory in makereloc() and makexref() by adding new
  31.  *        nodes to the current section if another pass is required
  32.  *        anyway.
  33.  * v0.5   (11.10.97) phx
  34.  *        getarg() works with \' and \" now.
  35.  * v0.4   (05.07.97) phx
  36.  *        R_PPC_TOC16 and R_PPC_REL14 support in makereloc() and makexref().
  37.  *        "(<term>)@l/h/ha" was not recognized.
  38.  *        A comment introducer '#' was erroneously treated as a macro
  39.  *        parameter in read_macro_params().
  40.  *        Undefined symbols are only automatically declared as externally
  41.  *        defined, if the -x option was given. Otherwise display an
  42.  *        error message.
  43.  *        Implementing backwards-evaluation of an expression in v0.3 was not
  44.  *        very smart (e.g. 4-1+2 => 1(!)) - changed to forward again... ;)
  45.  * v0.3   (20.04.97) phx
  46.  *        Bug in eval_expression() fixed, which sometimes caused the loss
  47.  *        of the last argument of an expression.
  48.  * v0.2   (25.03.97) phx
  49.  *        Writes ELF object for 32-bit PowerPC big-endian. Either absolute
  50.  *        or ELF output format may be selected. ELF is default for all
  51.  *        currently supported platforms. PPCasm supports nine different
  52.  *        relocation types (there are much more...).
  53.  *        Compiles and works also under NetBSD/amiga (68k).
  54.  *        Changed function declaration to 'new style' in all sources
  55.  *        (to avoid problems with '...' for example).
  56.  *        makexref() and makereloc() used wrong offset.
  57.  * v0.1   (11.03.97) phx
  58.  *        First test version with all PowerPC instructions and most
  59.  *        important directives. Only raw, absolute output.
  60.  * v0.0   (21.02.97) phx
  61.  *        File created.
  62.  */
  63.  
  64.  
  65. #define EVAL_C
  66. #include "ppcasm.h"
  67.  
  68.  
  69. char *getsymbol(struct GlobalVars *,char *);
  70. char *getarg(struct GlobalVars *,char *);
  71. char *skipspaces(char *);
  72. char *remquotes(char *);
  73. void checkEOL(char *);
  74. char *skipexpression(struct GlobalVars *,char *);
  75. void read_macro_params(struct GlobalVars *,struct ParsedLine *,
  76.                        struct MacroParams *,char *);
  77. char *getexp(struct GlobalVars *,char *,uint32 *,uint8);
  78. uint32 makereloc(struct GlobalVars *,struct Expression *);
  79. uint32 makexref(struct GlobalVars *,struct Expression *,uint8);
  80. char *getintexp(struct GlobalVars *,char *,uint32 *);
  81. char *eval_expression(struct GlobalVars *,struct Expression *,char *);
  82.  
  83. static uint32 hihalf(struct GlobalVars *,uint32);
  84. static uint32 lohalf(struct GlobalVars *,uint32);
  85. static uint32 read_hex(char *);
  86. static uint32 read_dec(char *);
  87. static uint32 read_oct(char *);
  88. static uint32 read_bin(char *);
  89. static uint32 read_str(char *);
  90.  
  91.  
  92.  
  93. /* table of valid symbol characters, 
  94.    0=invalid, 1=valid in whole symbol, 2=valid, but not as first char */
  95. static uint8 valid_symchars[256] = {
  96.   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  97.   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  98.   0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,  /* $ . */
  99.   2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,1,  /* 0-9 ? */
  100.   0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,  /* A-O */
  101.   1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,1,  /* P-Z _ */
  102.   0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,  /* a-o */
  103.   1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,  /* p-z */
  104.   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  105.   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  106.   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  107.   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  108.   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  109.   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  110.   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  111.   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
  112. };
  113.  
  114. /* table of valid argument characters, 
  115.    0=invalid, 1=valid, 2=valid, but indicates string */
  116. static uint8 valid_argchars[256] = {
  117.   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  118.   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  119.   0,0,2,0,1,0,0,2,0,0,0,0,0,0,1,0,  /* " $ ' . */
  120.   1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,1,  /* 0-9 ? */
  121.   0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,  /* A-O */
  122.   1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,1,  /* P-Z _ */
  123.   0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,  /* a-o */
  124.   1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,  /* p-z */
  125.   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  126.   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  127.   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  128.   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  129.   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  130.   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  131.   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  132.   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
  133. };
  134.  
  135. /* valid operators */
  136. #define NUMOPS 10
  137. static char valid_operators[NUMOPS] = {
  138.   '+','-','*','/','%','<','>','&','|','^'
  139. };
  140. #define MAXOPPRI 5
  141. static uint8 op_priority[NUMOPS] = {
  142.   4,4,5,5,5,3,3,2,0,1
  143. };
  144.  
  145.  
  146. char *getsymbol(struct GlobalVars *gv,char *s)
  147. /* read a symbol string into gv->strbuf */
  148. {
  149.   uint8 *vsc = valid_symchars;
  150.   char *b = gv->strbuf;
  151.   int bsize = STRBUFSIZE-2;
  152.  
  153.   if (*s == '@') {  /* '@' is allowed as first character */
  154.     *b++ = *s++;
  155.     bsize--;
  156.   }
  157.   if (vsc[(unsigned char)*s] == 1) {  /* first character valid? */
  158.     *b++ = *s++;
  159.     while (vsc[(unsigned char)*s] && bsize--)
  160.       *b++ = *s++;
  161.   }
  162.   *b = 0;
  163.   return (s);
  164. }
  165.  
  166.  
  167. char *getarg(struct GlobalVars *gv,char *s)
  168. /* read next argument into gv->strbuf */
  169. {
  170.   uint8 v,*vac = valid_argchars;
  171.   char c,*b = gv->strbuf;
  172.   int bsize = STRBUFSIZE-1;
  173.  
  174.   if (*s == '@') {  /* '@' is allowed as first character */
  175.     *b++ = *s++;
  176.     bsize--;
  177.   }
  178.   while ((v = vac[(unsigned char)*s]) && bsize--) {
  179.     *b++ = *s++;
  180.     if (v==2) {  /* string? */
  181.       c = *(s-1);
  182.       for (;;) {
  183.         if (bsize--) {
  184.           if (!(*b++ = *s))  /* string can only be terminated by EOL */
  185.             return (s);
  186.         }
  187.         else
  188.           return (s);
  189.         if (*s++ == c) {
  190.           if (*s==c || *(s-2)=='\\') {
  191.             if (bsize--)  /* "", '' \" or \' don't terminate the string */
  192.               *b++ = *s++;
  193.              else
  194.               return (s);
  195.           }
  196.           else
  197.             break;
  198.         }
  199.       }
  200.     }
  201.   }
  202.   *b = 0;
  203.   return (s);
  204. }
  205.  
  206.  
  207. char *skipspaces(char *s)
  208. /* advance string pointer to the first character, which is no white space */
  209. {
  210.   while (*s==' ' || *s=='\t')
  211.     ++s;
  212.   return (s);
  213. }
  214.  
  215.  
  216. char *remquotes(char *s)
  217. /* remove " or ', if present and return new strbuf-pointer */
  218. {
  219.   int len;
  220.   char c = *s;
  221.  
  222.   if (c=='\"' || c=='\'')  /* string is in quotes */
  223.     if (len = strlen(++s) - 1)
  224.       if (s[len] == c)
  225.         s[len] = 0;
  226.   return (s);
  227. }
  228.  
  229.  
  230. void checkEOL(char *s)
  231. /* check for illegal extra characters on line */
  232. {
  233.   s = skipspaces(s);
  234.   if (*s && *s!='#')  /* only comment is allowed as an extra character */
  235.     error(18);  /* extra characters on line */
  236. }
  237.  
  238.  
  239. char *skipexpression(struct GlobalVars *gv,char *s)
  240. {
  241.   char c;
  242.  
  243.   do {
  244.     s = getarg(gv,s);
  245.     s = skipspaces(s);
  246.     c = *s++;
  247.   }
  248.   while (c!=0 && c!='#' && c!=',');
  249.   return (--s);
  250. }
  251.  
  252.  
  253. void read_macro_params(struct GlobalVars *gv,struct ParsedLine *pl,
  254.                        struct MacroParams *mp,char *op)
  255. /* read parameters and store pointers to their first character */
  256. {
  257.   char c;
  258.  
  259.   mp->param[0] = mp->param0;
  260.   if (pl->branch_hint)
  261.     mp->param0[0] = pl->branch_hint>0 ? '+' : '-';
  262.   for (;;) {
  263.     op = skipspaces(op);
  264.     c = *op;
  265.     if (c!=0 && c!='#') {  /* another parameter? */
  266.       if (mp->narg < (MAX_MACPARAMS-1)) {
  267.         mp->param[++mp->narg] = op;
  268.         op = skipexpression(gv,op);
  269.         c = *op;
  270.         if (c==0 || c=='#') {
  271.           *op = 0;  /* end of line / start of comment */
  272.           return;
  273.         }
  274.         *op++ = 0;  /* next parameter */
  275.       }
  276.       else {
  277.         error(11);  /* too many macro parameters */
  278.         return;
  279.       } 
  280.     }
  281.     else
  282.       return;
  283.   }
  284. }
  285.  
  286.  
  287. char *getexp(struct GlobalVars *gv,char *s,uint32 *val,uint8 size)
  288. /* evaluate expression, create relocations or x-references, if required */
  289. {
  290.   struct Expression exp;
  291.  
  292.   s = eval_expression(gv,&exp,s);
  293.   if (exp.type != SYM_UNDEF) {
  294.     if (exp.reloctype==R_PPC_ADDR32 && size==2)
  295.       exp.reloctype = R_PPC_ADDR16;
  296.     switch (exp.type) {
  297.       case SYM_RELOC:
  298.         *val = makereloc(gv,&exp);  /* make relocation entry */
  299.         break;
  300.       case SYM_EXTERN:  /* reference to external symbol */
  301.         *val = makexref(gv,&exp,size);
  302.         break;
  303.       default:  /* SYM_ABS */
  304.         *val = exp.value;
  305.         break;
  306.     }
  307.   }
  308.   else
  309.     error(19);  /* undefined symbol */
  310.   return (s);
  311. }
  312.  
  313.  
  314. static uint32 hihalf(struct GlobalVars *gv,uint32 x)
  315. {
  316.   if (gv->signedexp)
  317.     return ((int32)x>>16);
  318.   else
  319.     return (x>>16);
  320. }
  321.  
  322.  
  323. static uint32 lohalf(struct GlobalVars *gv,uint32 x)
  324. {
  325.   if (gv->signedexp)
  326.     return ((int16)x);
  327.   else
  328.     return (x&0xffff);
  329. }
  330.  
  331.  
  332. uint32 makereloc(struct GlobalVars *gv,struct Expression *exp)
  333. /* make new relocation entry for current section */
  334. {
  335.   struct Reloc dummy,*reloc;
  336.  
  337.   if (gv->anotherpass) {
  338.     /* don't waste memory, if another pass is required anyway */
  339.     reloc = &dummy;
  340.   }
  341.   else {
  342.     reloc = alloc(sizeof(struct Reloc));
  343.     addtail(&gv->csect->reloclist,&reloc->n);
  344.   }
  345.   reloc->relocsect = exp->symbol->relsect;
  346.   reloc->offset = gv->csect->pc;
  347.   reloc->type = exp->reloctype;
  348.   reloc->addend = exp->value;
  349.   switch (exp->reloctype) {
  350.     case R_PPC_ADDR16_HA:
  351.     case R_PPC_ADDR16_HI:
  352.       reloc->offset += 2;
  353.       return (hihalf(gv,exp->value));
  354.     case R_PPC_ADDR16_LO:
  355.       reloc->offset += 2;
  356.       return (lohalf(gv,exp->value));
  357.     case R_PPC_ADDR16:
  358.     case R_PPC_SDAREL16:
  359.       reloc->offset += 2;
  360.       return (exp->value);
  361.     case R_PPC_REL14:
  362.     case R_PPC_REL14_BRTAKEN:
  363.     case R_PPC_REL14_BRNTAKEN:
  364.       if (gv->output != OFMT_ELF)
  365.         reloc->offset += 2;
  366.     default:
  367.       return (exp->value);
  368.   }
  369. }
  370.  
  371.  
  372. uint32 makexref(struct GlobalVars *gv,struct Expression *exp,uint8 size)
  373. {
  374.   struct XReference dummy,*xref;
  375.  
  376.   if (gv->anotherpass) {
  377.     /* don't waste memory, if another pass is required anyway */
  378.     xref = &dummy;
  379.   }
  380.   else {
  381.     xref = alloc(sizeof(struct XReference));
  382.     addtail(&gv->csect->xreflist,&xref->n);
  383.   }
  384.   xref->xsymbol = exp->symbol;
  385.   xref->offset = gv->csect->pc;
  386.   xref->addend = exp->value;
  387.   xref->type = exp->reloctype;
  388.   xref->size = size;
  389.   switch (exp->reloctype) {
  390.     case R_PPC_ADDR16_HA:
  391.     case R_PPC_ADDR16_HI:
  392.       xref->offset += 2;
  393.       return (hihalf(gv,exp->value));
  394.     case R_PPC_ADDR16_LO:
  395.       xref->offset += 2;
  396.       return (lohalf(gv,exp->value));
  397.     case R_PPC_ADDR16:
  398.     case R_PPC_SDAREL16:
  399.       xref->offset += 2;
  400.       return (exp->value);
  401.     case R_PPC_REL14:
  402.     case R_PPC_REL14_BRTAKEN:
  403.     case R_PPC_REL14_BRNTAKEN:
  404.       if (gv->output != OFMT_ELF)
  405.         xref->offset += 2;
  406.     default:
  407.       return (exp->value);
  408.   }
  409. }
  410.  
  411.  
  412. char *getintexp(struct GlobalVars *gv,char *s,uint32 *val)
  413. /* evaluate expression and check if absolute integer */
  414. {
  415.   struct Expression exp;
  416.  
  417.   s = eval_expression(gv,&exp,s);
  418.   if (exp.type != SYM_UNDEF) {
  419.     if (exp.type == SYM_ABS)
  420.       *val = exp.value;
  421.     else
  422.       error(24);  /* constant integer expression required */
  423.   }
  424.   else
  425.     error(19);  /* undefined symbol */
  426.   return (s);
  427. }
  428.  
  429.  
  430. char *eval_expression(struct GlobalVars *gv,struct Expression *exp_result,
  431.                       char *s)
  432. /* evaluate an integer expression and determine its type */
  433. {
  434.   struct Expression exp[EXPSTACKSIZE];
  435.   uint8 ops[EXPSTACKSIZE-1],op,ta,tb;
  436.   int i,j,k,exp_args=0;
  437.   uint8 unary;  /* unary operator, 0=none, 1=plus, 2=minus, 3=not */
  438.   char c;
  439.   char *arg=gv->strbuf;
  440.   struct Symbol *sym;
  441.  
  442.   exp_result->value = 0;
  443.   exp_result->type = SYM_UNDEF;
  444.  
  445.   /* build expression stack */
  446.   for (;;) {
  447.     unary = 0;
  448.     exp[exp_args].reloctype = R_PPC_ADDR32;
  449.  
  450.     for (;;) {
  451.       s = skipspaces(s);
  452.       s = getarg(gv,s);  /* try to get next argument */
  453.       if (c = *arg)
  454.         break;  /* got it */
  455.  
  456.       if ((c=*s++) == '(') {  /* beginning of a term? */
  457.         s = eval_expression(gv,&exp[exp_args],s);
  458.         if (*s++ != ')') {
  459.           error(21);  /* missing closing parenthesis */
  460.           s--;
  461.         }
  462.         *arg = 0;  /* expression in term is already evaluated */
  463.         break;
  464.       }
  465.  
  466.       if (c==0 || c=='#' || c==')') {
  467.         error(17);  /* missing argument */
  468.         s--;
  469.         c = 0;
  470.         break;
  471.       }
  472.  
  473.       if (unary)
  474.         error(20);  /* double unary operator */
  475.       else
  476.         switch (c) {
  477.           case '+':
  478.             unary = 1;
  479.             break;
  480.           case '-':
  481.             unary = 2;
  482.             break;
  483.           case '~':
  484.             unary = 3;
  485.             break;
  486.           default:
  487.             error(13);  /* syntax error */
  488.             break;
  489.         }
  490.     }
  491.  
  492.     if (!c)
  493.       break;  /* evaluate */
  494.  
  495.     if (c = *arg) {
  496.  
  497.       if (c>='0' && c<='9') {  /* numeric constant */
  498.         if (c=='0')
  499.           switch (arg[1]) {
  500.             case 'x':
  501.               exp[exp_args].value = read_hex(&arg[2]);
  502.               break;
  503.             case 'b':
  504.               exp[exp_args].value = read_bin(&arg[2]);
  505.               break;
  506.             case 0:
  507.               exp[exp_args].value = 0;
  508.               break;
  509.             default:
  510.               exp[exp_args].value = read_oct(&arg[1]);
  511.               break;
  512.           }
  513.         else
  514.           exp[exp_args].value = read_dec(arg);
  515.         exp[exp_args].type = SYM_ABS;
  516.       }
  517.  
  518.       else if (c=='\"' || c=='\'') {  /* string constant */
  519.         exp[exp_args].value = read_str(arg);
  520.         exp[exp_args].type = SYM_ABS;
  521.       }
  522.  
  523.       else {  /* get symbol value */
  524.         if (sym = search_symbol(gv,arg)) {
  525.           exp[exp_args].value = sym->value;
  526.           exp[exp_args].type = sym->type;
  527.           exp[exp_args].symbol = sym;
  528.         }
  529.         else {
  530.           if (gv->pass && gv->autoextern) {  /* pass 2? auto. decl. extern */
  531.             sym = add_symbol(gv,arg,SYM_EXTERN,0);
  532.             exp[exp_args].value = sym->value;
  533.             exp[exp_args].type = sym->type;
  534.             exp[exp_args].symbol = sym;
  535.           }
  536.           else {
  537.             exp[exp_args].value = 0;
  538.             exp[exp_args].type = SYM_UNDEF;
  539.           }
  540.         }
  541.       }
  542.     }
  543.  
  544.     if (unary) {
  545.       if (exp[exp_args].type >= SYM_RELOC)
  546.         error(22);  /* illegal operation for a relocatable expression */
  547.       else
  548.         switch (unary) {
  549.           case 2:  /* negate */
  550.             exp[exp_args].value = -exp[exp_args].value;
  551.             break;
  552.           case 3:  /* not */
  553.             exp[exp_args].value = ~exp[exp_args].value;
  554.             break;
  555.         }
  556.     }
  557.     if (exp[exp_args].type == SYM_ABS)
  558.       exp[exp_args].reloctype = R_NONE;
  559.  
  560.     /* check for operator */
  561.     s = skipspaces(s);
  562.     c = *s;
  563.     i = 0;
  564.     while (i<NUMOPS) {
  565.       if (c == valid_operators[i])
  566.         break;
  567.       i++;
  568.     }
  569.     if (i==NUMOPS)
  570.       break;  /* end of expression - evaluate */
  571.  
  572.     ops[exp_args++] = i;
  573.     if (*(++s) == c)
  574.       if (i==5 || i==6)  /* <<, >> */
  575.         ++s;
  576.   }
  577.  
  578.   /* evaluate expression stack */
  579.   for (i=MAXOPPRI; i>=0; i--) {
  580.     for (j=0; j<exp_args; ) {
  581.       op = ops[j];
  582.       if (op_priority[op] == i) {
  583.         if (!(ta = exp[j].type) || !(tb = exp[j+1].type)) {
  584.           exp[j].value = 0;
  585.           exp[j].type = SYM_UNDEF;
  586.           exp[j].reloctype = R_PPC_ADDR32;
  587.         }
  588.         else switch(op) {
  589.  
  590.           case 0:  /* + */
  591.             if (ta != tb) {
  592.               if (ta == SYM_ABS) {
  593.                 exp[j].type = tb;  /* reloc + abs = reloc */
  594.                 exp[j].reloctype = exp[j+1].reloctype;
  595.                 exp[j].symbol = exp[j+1].symbol;
  596.               }
  597.               else if (tb != SYM_ABS) {
  598.                 error(22);  /* illegal reloc operation */
  599.                 break;
  600.               }          
  601.             }
  602.             else if (ta >= SYM_RELOC) {
  603.               error(22);
  604.               break;
  605.             }
  606.             exp[j].value += exp[j+1].value;
  607.             break;
  608.  
  609.           case 1:  /* - */
  610.             if (ta != tb) {  /* reloc - abs = reloc */
  611.               if (tb != SYM_ABS) {
  612.                 error(22);
  613.                 break;
  614.               }
  615.             }
  616.             else {  /* reloc - reloc = abs  |  abs - abs = abs */
  617.               if (ta != SYM_EXTERN) {  /* extern - extern  not supported */
  618.                 exp[j].type = SYM_ABS;
  619.                 if (ta == SYM_RELOC)
  620.                   if (exp[j].symbol->relsect != exp[j+1].symbol->relsect)
  621.                     error(23);  /* symbols reside in different sections */
  622.               }
  623.               else {
  624.                 error(22);
  625.                 break;
  626.               }
  627.             }
  628.             exp[j].value -= exp[j+1].value;
  629.             break;
  630.  
  631.           case 2:  /* * */
  632.             if (ta == tb == SYM_ABS)
  633.               exp[j].value *= exp[j+1].value;
  634.             else
  635.               error(22);
  636.             break;
  637.  
  638.           case 3:  /* / */
  639.             if (ta == tb == SYM_ABS)
  640.               exp[j].value /= exp[j+1].value;
  641.             else
  642.               error(22);
  643.             break;
  644.  
  645.           case 4:  /* % */
  646.             if (ta == tb == SYM_ABS)
  647.               exp[j].value %= exp[j+1].value;
  648.             else
  649.               error(22);
  650.             break;
  651.  
  652.           case 5:  /* << */
  653.             if (ta == tb == SYM_ABS)
  654.               exp[j].value <<= exp[j+1].value;
  655.             else
  656.               error(22);
  657.             break;
  658.  
  659.           case 6:  /* << */
  660.             if (ta == tb == SYM_ABS)
  661.               exp[j].value >>= exp[j+1].value;
  662.             else
  663.               error(22);
  664.             break;
  665.  
  666.           case 7:  /* & */
  667.             if (ta == tb == SYM_ABS)
  668.               exp[j].value &= exp[j+1].value;
  669.             else
  670.               error(22);
  671.             break;
  672.  
  673.           case 8:  /* | */
  674.             if (ta == tb == SYM_ABS)
  675.               exp[j].value |= exp[j+1].value;
  676.             else
  677.               error(22);
  678.             break;
  679.  
  680.           case 9:  /* ^ */
  681.             if (ta == tb == SYM_ABS)
  682.               exp[j].value ^= exp[j+1].value;
  683.             else
  684.               error(22);
  685.             break;
  686.         }
  687.  
  688.         exp_args--;
  689.         for (k=j; k<exp_args; k++) {
  690.           memcpy(&exp[k+1],&exp[k+2],sizeof(struct Expression));
  691.           ops[k] = ops[k+1];
  692.         }
  693.       }
  694.       else
  695.         j++;
  696.     }
  697.     if (exp_args==0)
  698.       break;
  699.   }
  700.  
  701.   memcpy(exp_result,&exp[0],sizeof(struct Expression));
  702.   if (*s == '@') {  /* check for @xxx additions */
  703.     s++;
  704.     switch (tolower((unsigned char)*s++)) {
  705.       case 'l':  /* symbol@l : lower half-word */
  706.         if (exp_result->type == SYM_ABS) {
  707.           exp_result->reloctype = R_NONE;
  708.           exp_result->value = lohalf(gv,exp_result->value);
  709.         }
  710.         else
  711.           exp_result->reloctype = R_PPC_ADDR16_LO;
  712.         break;
  713.       case 'h':
  714.         if (tolower((unsigned char)*s) == 'a') {
  715.           s++;  /* symbol@ha : higher (addi) */
  716.           if (exp_result->type == SYM_ABS) {
  717.             exp_result->reloctype = R_NONE;
  718.             if (exp_result->value & 0x8000)
  719.               exp_result->value = hihalf(gv,exp_result->value + 0x10000);
  720.             else
  721.               exp_result->value = hihalf(gv,exp_result->value);
  722.           }
  723.           else
  724.             exp_result->reloctype = R_PPC_ADDR16_HA;
  725.         }
  726.         else {  /* symbol@h : higher half-word */
  727.           if (exp_result->type == SYM_ABS) {
  728.             exp_result->reloctype = R_NONE;
  729.             exp_result->value = hihalf(gv,exp_result->value);
  730.           }
  731.           else
  732.             exp_result->reloctype = R_PPC_ADDR16_HI;
  733.         }
  734.         break;
  735.       case 's':  /* symbol@sdarx, symbol@sdax : small data offset */
  736.         if (!strncmpnc(s,"darx",4)) {
  737.           s += 4;
  738.           exp_result->reloctype = R_PPC_SDAREL16;
  739.         }
  740.         else if (!strncmpnc(s,"dax",3)) {
  741.           s += 3;
  742.           exp_result->reloctype = R_PPC_SDAREL16;
  743.         }
  744.         else
  745.           s -= 2;
  746.         break;
  747.       default:
  748.         s -= 2;
  749.         break;
  750.     }
  751.   }
  752.  
  753.   return (s);
  754. }
  755.  
  756.  
  757. static uint32 read_hex(char *s)
  758. {
  759.   uint32 x=0,y;
  760.  
  761.   while (y = (unsigned char)*s++) {
  762.     if (y > '9')
  763.       y = (y & 0x5f) - 7;
  764.     x <<= 4;
  765.     x += y - '0';
  766.   }
  767.   return (x);
  768. }
  769.  
  770.  
  771. static uint32 read_dec(char *s)
  772. {
  773.   uint32 x=0,y;
  774.  
  775.   while (y = (unsigned char)*s++) {
  776.     x *= 10;
  777.     x += y - '0';
  778.   }
  779.   return (x);
  780. }
  781.  
  782.  
  783. static uint32 read_oct(char *s)
  784. {
  785.   uint32 x=0,y;
  786.  
  787.   while (y = (unsigned char)*s++) {
  788.     x <<= 3;
  789.     x += y - '0';
  790.   }
  791.   return (x);
  792. }
  793.  
  794.  
  795. static uint32 read_bin(char *s)
  796. {
  797.   uint32 x=0,y;
  798.  
  799.   while (y = (unsigned char)*s++) {
  800.     x <<= 1;
  801.     x += y & 1;
  802.   }
  803.   return (x);
  804. }
  805.  
  806.  
  807. static uint32 read_str(char *s)
  808. {
  809.   uint32 x=0;
  810.   char c,sc=*s++;
  811.  
  812.   while (c = *s++) {
  813.     if (c==sc) {
  814.       if (*s==sc)   /* "" is converted into " */
  815.         s++;
  816.       else
  817.         break;
  818.     }
  819.     else if (c=='\\') {
  820.       if (!(c = escchar(*s++)))
  821.         break;
  822.     }
  823.     x <<= 8;
  824.     x += (unsigned char)c;
  825.   }
  826.   return (x);
  827. }
  828.